using Game.Scripts.Constant;
using Game.Scripts.Entity;
using Game.Scripts.Entity.UI.NextGameMenu;
using Game.Scripts.ScriptableObject;
using Sirenix.OdinInspector;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.Assertions;
using Zenject;

namespace Game.Scripts.Service
{
    public class GameService : MonoBehaviour
    {
        private IkunBus _ikunBus;
        private ObjectPoolService _objectPoolService;
        [ReadOnly] public LaunchConfigScriptableObject launchConfigScriptableObject;
        [SerializeField] private LaunchConfigScriptableObject devLaunchConfig;
        [SerializeField] private LaunchConfigScriptableObject prodLaunchConfig;
        [HideInInspector] public LaunchOption launchOption;
        public TextMeshProUGUI playerScore;
        [HideInInspector] public ReactiveProperty<int> playerHealth = new ReactiveProperty<int>();
        [SerializeField] private Transform playerHealthContainer;
        [HideInInspector] public int playerMaxHealth;
        private NextGameMenu _nextGameMenu;
        private RoadTileService _roadTileService;
        [ReadOnly] public ReactiveProperty<int> currentGameLevel;
        public GameLevelConfigScriptableObject gameLevelConfig;

        [Inject]
        public void Construct(IkunBus ikunBus, ObjectPoolService objectPoolService, NextGameMenu nextGameMenu,
            RoadTileService roadTileService)
        {
            _ikunBus = ikunBus;
            _objectPoolService = objectPoolService;
            _nextGameMenu = nextGameMenu;
            _roadTileService = roadTileService;
        }


        private void Awake()
        {
            Assert.IsNotNull(launchConfigScriptableObject);
            launchOption = launchConfigScriptableObject.launchOption;
            playerHealth.Value = launchConfigScriptableObject.playerInitialHealth;
            playerMaxHealth = launchConfigScriptableObject.playerMaxHealth;
            currentGameLevel.Value = PlayerPrefs.GetInt(StorageKey.PlayerGameLevel.ToString(), 0);
        }


        [ButtonGroup("LaunchOption")]
        private void LaunchInDevMode()
        {
            launchConfigScriptableObject = devLaunchConfig;
        }


        [ButtonGroup("LaunchOption")]
        private void LaunchInProdMode()
        {
            launchConfigScriptableObject = prodLaunchConfig;
        }


        public void HandleGameRestart()
        {
            _ikunBus.PauseBusState();
            _nextGameMenu.Open(NextGameMenuOpenState.Restart);
        }



        private void Start()
        {
            playerHealth.Subscribe(next =>
            {
                if (next == 0)
                {
                    HandleGameRestart();
                    return;
                }

                int playerHealthPrev = 0;

                foreach (Transform child in playerHealthContainer)
                {
                    if (child.gameObject.activeInHierarchy)
                    {
                        playerHealthPrev += 1;
                    }
                }


                int diff = next - playerHealthPrev;
                if (diff > 0)
                {
                    for (int i = 0; i < diff; i++)
                    {
                        GameObject heart = _objectPoolService.healthObjectPool.Get();
                        heart.transform.SetParent(playerHealthContainer);
                    }
                }
                else if (diff < 0)
                {
                    for (int i = playerHealthPrev - 1; i >= 0; i--)
                    {
                        if (diff < 0)
                        {
                            _objectPoolService.healthObjectPool.Release(playerHealthContainer.GetChild(i).gameObject);
                            diff += 1;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            });
        }

        public void ResetGameState()
        {
            playerHealth.Value = launchConfigScriptableObject.playerInitialHealth;
            _ikunBus.ResetBusState();
            _roadTileService.ResetTilesState();
        }


        public void StartGame()
        {
            _ikunBus.SetIkunBusState(IkunBusState.Moving);
        }


        public void RestartGame()
        {
            currentGameLevel.SetValueAndForceNotify(PlayerPrefs.GetInt(StorageKey.PlayerGameLevel.ToString(), 0));
            StartGame();
        }


        public void GoToNextGameLevel()
        {
            currentGameLevel.Value += 1;
            PlayerPrefs.SetInt(StorageKey.PlayerGameLevel.ToString(), currentGameLevel.Value);
            StartGame();
        }
    }
}